package com.youlu.campus.admin.auth;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.admin.utils.IpUtils;
import com.youlu.campus.common.utils.SM2CryptUtils;
import com.youlu.campus.entity.WechatAuthBlackList;
import com.youlu.campus.service.platform.PlatformVisitorRecordService;
import com.youlu.campus.service.system.SystemIpLimitService;
import com.youlu.campus.service.wechat.WechatAuthBlackListService;
import com.yuelin.infrastructure.quantum.common.QResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Objects;

/**
 * 优先处理短信和七牛云
 */
@Slf4j
//@WebFilter(filterName = "publicFilter", urlPatterns = "/*")
public class PublicFilter implements Filter {
    @Autowired
    private SystemIpLimitService systemIpLimitService;
    @Autowired
    private WechatAuthBlackListService wechatAuthBlackListService;
    @Value("${server.servlet.context-path}")
    private String prefix;
    @Value("${sys.checkUrl}")
    private String sysCheckUrl;
    @Autowired
    private PlatformVisitorRecordService platformVisitorRecordService;

    /**
     * sysAppId+timestamp+nonce+signature
     *
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //检查url路径
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        String url = req.getRequestURI();
        log.info(":>>> 开始过滤 public请求,URL:{}", url);
        url = url.replaceFirst(prefix, "");
        boolean needCheck = this.needCheck(url);
        if (!needCheck) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        String ip = IpUtils.getIpAddr(req);
        String sysAppId = req.getHeader("pSysAppId");
        String timestamp = req.getHeader("pTimestamp");
        String nonce = req.getHeader("pNonce");
        String signature = req.getHeader("pSignature");
        log.info(":>>> 传入的参数:pSysAppId:{},pTimestamp:{},pNonce:{},pSignature:{}",
                sysAppId, timestamp, nonce, signature);
        if (StringUtils.isBlank(sysAppId) || StringUtils.isBlank(timestamp) ||
                StringUtils.isBlank(nonce) || StringUtils.isBlank(signature)) {
            log.error(":>>> 请求参数为空，非法请求");
            writeJson(QResult.fail(405, "服务器异常,异常编号2"), resp);
            return;
        }
        WechatAuthBlackList we = wechatAuthBlackListService.findBySysAppId(sysAppId);
        if (Objects.isNull(we)) {
            log.error(":>>> 服务器异常,异常编号3");
            writeJson(QResult.fail(406, "服务器异常,异常编号3"), resp);
            return;
        }
        boolean passed = checkSignature(we, timestamp, nonce,
                signature);
        if (!passed) {
            log.error(":>>> 服务器异常,异常编号4");
            writeJson(QResult.fail(407, "服务器异常,异常编号4"), resp);
            return;
        }
        filterChain.doFilter(servletRequest, servletResponse);

    }

    @Override
    public void destroy() {

    }

    private void writeJson(QResult result, HttpServletResponse response) {
        PrintWriter out = null;
        try {
            response.setStatus(HttpServletResponse.SC_OK);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            out = response.getWriter();
            out.write(JSON.toJSONString(result));
        } catch (IOException e) {
            log.warn("io exception {}", e);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    private boolean checkSignature(WechatAuthBlackList we, String timestamp, String nonce,
                                   String signature) {
        try {
            String timeStampD = SM2CryptUtils.decrypt(timestamp, we.getPrivatekey());
            String nonceD = SM2CryptUtils.decrypt(nonce, we.getPrivatekey());
            String fromSignature = we.getSysAppId() + "&" + timeStampD + "&" + nonceD;
            String signatureDe = SM2CryptUtils.decrypt(signature, we.getPrivatekey());
            Long timestampL = Long.valueOf(timeStampD);
            if ((System.currentTimeMillis() - timestampL) >= 5 * 60 * 1000L) {
                log.error(":>>> 时间戳超过5分钟，过期请求");
                return false;
            }
            if (fromSignature.equals(signatureDe)) {
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error(":>>> 解密错误:{}", e);
            return false;
        }
    }

    private boolean needCheck(String url) {
        if (sysCheckUrl.contains(url)) {
            return true;
        }
        return false;
    }
}
